package com.fishingwithme.android.ui.viewmodels

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fishingwithme.android.data.model.AddCircleDto
import com.fishingwithme.android.data.model.Position
import com.fishingwithme.android.data.model.PolygonOrigin
import com.fishingwithme.android.data.repository.FishingRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject

data class AddCircleUiState(
    val isLoading: Boolean = false,
    val error: String? = null,
    val isSaveSuccess: Boolean = false,
    var title: String = "",
    var description: String = "",
    var latitude: Double = 0.0,
    var longitude: Double = 0.0,
    var points: List<Position> = listOf(),
    var pics: List<String> = listOf()
)

@HiltViewModel
class AddCircleModel @Inject constructor(
    private val repository: FishingRepository
) : ViewModel() {
    private val _uiState = MutableStateFlow(AddCircleUiState())
    val uiState: StateFlow<AddCircleUiState> = _uiState.asStateFlow()
    
    fun updateTitle(title: String) {
        _uiState.update { it.copy(title = title) }
    }
    
    fun updateDescription(description: String) {
        _uiState.update { it.copy(description = description) }
    }
    
    fun updateLocation(latitude: Double, longitude: Double) {
        _uiState.update { it.copy(latitude = latitude, longitude = longitude) }
    }
    
    fun updatePoints(points: List<Position>) {
        // Calculate the center point of the polygon
        val center = calculatePolygonCenter(points)
        _uiState.update { 
            it.copy(
                points = points,
                latitude = center?.latitude ?: 0.0,
                longitude = center?.longitude ?: 0.0
            ) 
        }
    }
    
    /**
     * Calculate the centroid (center point) of a polygon
     * @param points List of positions defining the polygon vertices
     * @return Position representing the centroid, or null if calculation is not possible
     */
    private fun calculatePolygonCenter(points: List<Position>): Position? {
        if (points.isEmpty()) return null
        
        // For a single point, return that point
        if (points.size == 1) return points[0]
        
        // For two points, return the midpoint
        if (points.size == 2) {
            return Position(
                latitude = (points[0].latitude + points[1].latitude) / 2.0,
                longitude = (points[0].longitude + points[1].longitude) / 2.0
            )
        }
        
        // For polygons with 3 or more points, calculate the centroid
        var area = 0.0
        var cx = 0.0
        var cy = 0.0
        
        for (i in points.indices) {
            val p1 = points[i]
            val p2 = points[(i + 1) % points.size]
            
            val cross = p1.longitude * p2.latitude - p2.longitude * p1.latitude
            area += cross
            cx += (p1.longitude + p2.longitude) * cross
            cy += (p1.latitude + p2.latitude) * cross
        }
        
        if (area == 0.0) {
            // If area is zero, return the first point
            return points[0]
        }
        
        area /= 2.0
        cx /= (6.0 * area)
        cy /= (6.0 * area)
        
        return Position(latitude = cy, longitude = cx)
    }
    
    fun updatePics(pics: List<String>) {
        _uiState.update { it.copy(pics = pics) }
    }
    
    fun addCircle() {
        val state = _uiState.value
        
        // Validate form
        if (state.title.isBlank()) {
            _uiState.update { it.copy(error = "请输入圈子标题") }
            return
        }
        
        if (state.latitude == 0.0 && state.longitude == 0.0) {
            _uiState.update { it.copy(error = "请选择位置") }
            return
        }
        
        if (state.pics.isEmpty()) {
            _uiState.update { it.copy(error = "请至少上传一张图片") }
            return
        }
        
        val dto = AddCircleDto(
            latitude = state.latitude,
            longitude = state.longitude,
            points = state.points,
            title = state.title,
            description = state.description,
            pics = state.pics
        )
        
        viewModelScope.launch {
            _uiState.update { it.copy(isLoading = true, error = null, isSaveSuccess = false) }
            try {
                val result = repository.addCircle(dto).firstOrNull()

                if (result == null) {
                    _uiState.update {
                        it.copy(
                            error = "未获取到保存结果",
                            isLoading = false,
                            isSaveSuccess = false
                        )
                    }
                } else {
                    result.fold(
                        onSuccess = {
                            _uiState.update {
                                it.copy(
                                    error = null,
                                    isLoading = false,
                                    isSaveSuccess = true
                                )
                            }
                        },
                        onFailure = {
                            _uiState.update {
                                it.copy(
                                    error = "保存失败",
                                    isLoading = false,
                                    isSaveSuccess = false
                                )
                            }
                        }
                    )
                }
            } catch (e: Exception) {
                _uiState.update { 
                    it.copy(
                        error = "保存时发生错误",
                        isLoading = false,
                        isSaveSuccess = false
                    ) 
                }
            }
        }
    }

    suspend fun uploadFile(file: File): Flow<Result<String>> {
        return repository.uploadFile(file)
    }
    
    fun clearError() {
        _uiState.update { it.copy(error = null) }
    }
    
    fun resetSaveState() {
        _uiState.update { it.copy(isSaveSuccess = false) }
    }
}